package com.qimu.saiyou.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qimu.saiyou.common.ErrorCode;
import com.qimu.saiyou.constant.CommonConstant;
import com.qimu.saiyou.exception.BusinessException;
import com.qimu.saiyou.mapper.CommentMapper;
import com.qimu.saiyou.model.dto.compete.CompeteQueryRequest;
import com.qimu.saiyou.model.entity.Comment;
import com.qimu.saiyou.model.entity.CommentLike;
import com.qimu.saiyou.model.entity.User;
import com.qimu.saiyou.model.vo.CommentVo;
import com.qimu.saiyou.model.vo.UserVO;
import com.qimu.saiyou.service.CommentLikeService;
import com.qimu.saiyou.service.CommentService;
import com.qimu.saiyou.service.UserService;
import com.qimu.saiyou.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: FeiXiang
 * @description 针对表【comment(评论表)】的数据库操作Service实现
 * @createDate 2024-03-28 16:03:50
 */
@Slf4j
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
        implements CommentService {
    @Resource
    private RedisTemplate<String, UserVO> redisTemplate;
    @Resource
    @Lazy
    private CommentLikeService commentLikeService;
    @Resource
    private UserService userService;

    @Override
    public void validComment(Comment comment, boolean add) {
        if (comment == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = comment.getId();
        Long parentId = comment.getParentId();
        String address = comment.getAddress();
        Long postId = comment.getPostId();
        Long userId = comment.getUserId();
        String content = comment.getContent();
        Integer likes = comment.getLikes();
        String contentImg = comment.getContentImg();
        Date createTime = comment.getCreateTime();
        Date updateTime = comment.getUpdateTime();

        if (add) {
            if (ObjectUtils.anyNull(postId)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            if (StringUtils.isBlank(content)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "评论内容不能为空");
            }
        }
        if (StringUtils.isNotBlank(content) && content.length() > 255) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "评论内容不能超过255个字符");
        }
    }

    @Override
    public List<CommentVo> firstComment(List<CommentVo> comments) {
        // 存储父评论为根评论-1的评论
        List<CommentVo> list = new ArrayList<>();
        for (CommentVo comment : comments) {
            // 其父id小于0则为第一级别的评论
            if (ObjectUtils.isEmpty(comment.getParentId())) {
                // 我们将该评论下的所有评论都查出来
                List<CommentVo> commentVoList = findReply(comments, comment.getId())
                        .stream()
                        .sorted(Comparator.comparing(CommentVo::getCreateTime).reversed())
                        .collect(Collectors.toList());
                CommentVo.Reply reply = new CommentVo.Reply();
                reply.setTotal(commentVoList.size());
                reply.setList(commentVoList);
                comment.setReply(reply);
                // 这就是我们最终数组中的Comment
                Long count = commentLikeService.lambdaQuery().eq(CommentLike::getCommentId, comment.getId()).count();
                comment.setLikes(Math.toIntExact(count));
                list.add(comment);
            }
        }
        return list.stream()
                .sorted(Comparator.comparing(CommentVo::getCreateTime).reversed())
                .collect(Collectors.toList());
    }

    @NotNull
    public CommentVo getCommentVo(Comment com) {
        CommentVo commentVo1 = new CommentVo();
        BeanUtils.copyProperties(com, commentVo1);
        UserVO userVo = redisTemplate.opsForValue().get("user:" + com.getUserId());
        if (userVo != null) {
            log.info("从缓存中获取用户信息" + userVo);
            commentVo1.setUser(userVo);
            return commentVo1;
        }
        User user = userService.getById(com.getUserId());
        UserVO userVO = new UserVO();
        if (user != null) {
            BeanUtils.copyProperties(user, userVO);
        }
        commentVo1.setUser(userVO);
        redisTemplate.opsForValue().set("user:" + com.getUserId(), userVO, 1, TimeUnit.MINUTES);
        return commentVo1;
    }

    @Override
    public QueryWrapper<Comment> getQueryWrapper(CompeteQueryRequest competeQueryRequest) {
        QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
        if (competeQueryRequest == null) {
            return queryWrapper;
        }
        Long id = competeQueryRequest.getId();
        Long teamId = competeQueryRequest.getTeamId();
        Long competitionId = competeQueryRequest.getCompetitionId();
        int current = competeQueryRequest.getCurrent();
        int pageSize = competeQueryRequest.getPageSize();
        String sortField = competeQueryRequest.getSortField();
        String sortOrder = competeQueryRequest.getSortOrder();
        String searchText = competeQueryRequest.getSearchText();
        Integer status = competeQueryRequest.getStatus();

        // 拼接查询条件
        if (StringUtils.isNotBlank(searchText)) {
            queryWrapper.and(qw -> qw.lambda().like(Comment::getContent, searchText).or().like(Comment::getAddress, searchText));
        }
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(status), "status", status);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    /**
     * @param comments 我们所有的该博客下的评论
     * @param targetId 我们要查到的目标父id
     * @return 返回该评论下的所有评论
     */
    public List<CommentVo> findReply(List<CommentVo> comments, Long targetId) {
        // 第一级别评论的子评论集合
        ArrayList<CommentVo> reply = new ArrayList<>();
        for (CommentVo comment : comments) {
            // 发现该评论的父id为targetId就将这个评论加入子评论集合
            if (find(comment.getParentId(), targetId)) {
                Long count = commentLikeService.lambdaQuery().eq(CommentLike::getCommentId, comment.getId()).count();
                comment.setLikes(Math.toIntExact(count));
                reply.add(comment);
            }
        }
        return reply;
    }

    public boolean find(Long id, Long target) {
        // 不将第一节评论本身加入自身的子评论集合
        if (ObjectUtils.isEmpty(id)) {
            return false;
        }
        // 如果父id等于target，那么该评论就是id为target评论的子评论
        if (id.equals(target)) {
            return true;
        } else {
            Comment comment = this.getById(id);
            if (comment == null) {
                return false;
            }
            // 否则就再向上找
            return find(comment.getParentId(), target);
        }
    }
}




